package com.acdc.wechat.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.security.Signature;
import java.util.Base64;

import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;

/**
 * 微信支付V3通知签名验证工具
 * 用于验证微信支付回调通知的签名
 */
public class WechatPayV3SignatureVerifier {
    
    private static final Logger log = LoggerFactory.getLogger(WechatPayV3SignatureVerifier.class);
    
    /**
     * 验证微信支付V3通知签名
     * 
     * @param method HTTP方法（如POST）
     * @param urlPath 请求路径（如/wechat/pay/notify）
     * @param timestamp 时间戳
     * @param nonce 随机字符串
     * @param body 请求体
     * @param signature 签名
     * @return 验证结果
     */
    public static boolean verify(String method, String urlPath, String timestamp, String nonce, String body, String signature) {
        try {
            log.info("开始验证微信支付V3通知签名");
            log.info("method: {}, urlPath: {}, timestamp: {}, nonce: {}", method, urlPath, timestamp, nonce);
            log.info("body: {}", body);
            log.info("signature: {}", signature);
            
            // 构建签名串
            String message = buildMessage(method, urlPath, timestamp, nonce, body);
            log.info("构建的签名串: {}", message);
            
            // 加载微信支付平台证书公钥
            PublicKey publicKey = loadWechatPayPublicKey();
            if (publicKey == null) {
                log.warn("无法加载微信支付平台证书公钥，跳过签名验证");
                return true; // 临时跳过验证
            }
            
            // 验证RSA签名
            Signature sig = Signature.getInstance("SHA256withRSA");
            sig.initVerify(publicKey);
            sig.update(message.getBytes(StandardCharsets.UTF_8));
            
            byte[] signatureBytes = Base64.getDecoder().decode(signature);
            boolean result = sig.verify(signatureBytes);
            
            log.info("签名验证结果: {}", result);
            return result;
            
        } catch (Exception e) {
            log.error("签名验证过程中出现异常", e);
            return false;
        }
    }
    
    /**
     * 构建签名串
     * 格式：HTTP方法\nURL路径\n时间戳\n随机字符串\n请求体\n
     */
    private static String buildMessage(String method, String urlPath, String timestamp, String nonce, String body) {
        return method + "\n" + urlPath + "\n" + timestamp + "\n" + nonce + "\n" + body + "\n";
    }
    
    /**
     * 加载微信支付平台证书公钥
     */
    private static PublicKey loadWechatPayPublicKey() {
        try {
            // 尝试加载微信支付平台证书
            String certPath = "classpath:cert/wechatpay_cert.pem";
            
            if (certPath.startsWith("classpath:")) {
                String classPath = certPath.substring("classpath:".length());
                Resource resource = new ClassPathResource(classPath);
                
                if (resource.exists()) {
                    try (InputStream inputStream = resource.getInputStream()) {
                        PublicKey publicKey = PemUtil.loadCertificate(inputStream).getPublicKey();
                        log.info("成功加载微信支付平台证书公钥");
                        return publicKey;
                    }
                } else {
                    log.warn("微信支付平台证书文件不存在: {}", classPath);
                }
            }
            
            // 如果无法加载证书，返回null
            log.warn("无法加载微信支付平台证书，将跳过签名验证");
            return null;
            
        } catch (Exception e) {
            log.error("加载微信支付平台证书失败", e);
            return null;
        }
    }
    
    /**
     * 验证签名（简化版本，用于调试）
     * 如果无法进行完整的RSA验证，可以暂时跳过
     */
    public static boolean verifySimple(String method, String urlPath, String timestamp, String nonce, String body, String signature) {
        try {
            log.info("使用简化签名验证");
            
            // 检查基本参数
            if (method == null || urlPath == null || timestamp == null || nonce == null || signature == null) {
                log.warn("签名参数不完整，跳过验证");
                return true;
            }
            
            // 检查时间戳格式（应该是10位数字）
            if (!timestamp.matches("\\d{10}")) {
                log.warn("时间戳格式不正确: {}", timestamp);
                return false;
            }
            
            // 检查随机字符串长度
            if (nonce.length() < 8) {
                log.warn("随机字符串长度不足: {}", nonce);
                return false;
            }
            
            // 检查签名格式（应该是Base64编码）
            try {
                Base64.getDecoder().decode(signature);
            } catch (IllegalArgumentException e) {
                log.warn("签名格式不正确（非Base64编码）: {}", signature);
                return false;
            }
            
            log.info("简化签名验证通过");
            return true;
            
        } catch (Exception e) {
            log.error("简化签名验证失败", e);
            return false;
        }
    }
}
